#include <Windows.h>

#undef min  // <-- this will definitely
#undef max // <-- get rid of the definitions

#include "NxPhysics.h"
#include "NxCooking.h"
#include "UserAllocator.h"

#include "D3DX10Math.h"

//#include "DrawObjects.cpp"
//#include "Actors.h"
//#include "Joints.h"

//#include "UserData.h"
//#include "Stream.h"
//#include "UpdateTime.h"
//#include "DebugRenderer.h"
//#include "ErrorStream.h"
//#include "CommonCode2.h"

enum partEnum
{
	HEAD,
	TORSO,
	PELVIS,
	UPPER_ARM_L,
	UPPER_ARM_R,
	FOREARM_L,
	FOREARM_R,
	HAND_L,
	HAND_R,
	THIGH_L,
	THIGH_R,
	CALF_L,
	CALF_R,
	FOOT_L,
	FOOT_R
};

class Ragdoll
{
	public:

	//NxActor* root;

	NxActor* head;
	NxActor* torso;
	NxActor* pelvis;
	NxActor* leftUpperArm;
	NxActor* rightUpperArm;
	NxActor* leftForeArm;
	NxActor* rightForeArm;
	NxActor* leftHand;
	NxActor* rightHand;
	NxActor* leftThigh;
	NxActor* rightThigh;
	NxActor* leftCalf;
	NxActor* rightCalf;
	NxActor* leftFoot;
	NxActor* rightFoot;

	//NxFixedJoint* glued;

	NxSphericalJoint* neck;
	NxSphericalJoint* leftShoulder;
	NxSphericalJoint* rightShoulder;
	NxSphericalJoint* spine;
	NxSphericalJoint* leftHip;
	NxSphericalJoint* rightHip;

	NxRevoluteJoint* leftElbow;
	NxRevoluteJoint* rightElbow;
	NxSphericalJoint* leftWrist;
	NxSphericalJoint* rightWrist;
	NxRevoluteJoint* leftKnee;
	NxRevoluteJoint* rightKnee;
	NxRevoluteJoint* leftAnkle;
	NxRevoluteJoint* rightAnkle;

	Ragdoll(const NxVec3& pos);

};

class Physixer
{

	private:
		// Actor globals
		NxActor* groundPlane;
		Ragdoll* guy;

		// Physics SDK globals
		NxPhysicsSDK*     gPhysicsSDK;
		NxScene*          gScene;
		NxVec3            gDefaultGravity;

		// Force globals
		NxVec3 gForceVec;
		NxReal gForceStrength;
		bool bForceMode;

		NxReal gKinematicVelocity;



		NxI32 gNbTouchedBodies;

		NxReal gDeltaTime;

		UserAllocator* gAllocator;

		


	public:

		// Focus actor and shape
		NxActor* gSelectedActor;
		NxShape* gSelectedShape;

		unsigned int previousTime;

		Physixer();

		void		InitNx();
		bool 		IsSelectable(NxActor* actor);
		void 		SelectNextActor();
		void 		SelectNextShapeOnActor(NxActor* actor);

		void		RotateActor(NxActor* actor, D3DXVECTOR3 *rot);

		NxVec3 		ApplyForceToActor(NxActor* actor, const NxVec3& forceDir, const NxReal forceStrength, bool forceMode);
		NxVec3 		HoverActor(NxActor* actor);
		NxVec3 		ApplyForceToActorAtShape(NxActor* actor, NxShape* shape, const NxVec3& forceDir, const NxReal forceStrength, bool forceMode, bool shapeSelectMode);
		NxVec3 		ApplyVelocityToActor(NxActor* actor, const NxVec3& velDir, const NxReal velStrength, bool velMode, const NxReal velScale);
		NxVec3 		MoveActor(NxActor* actor, D3DXVECTOR3 *mov, D3DXVECTOR3 *grav);
		void 		ReleaseNx();
		void 		ResetNx();
		void 		StartPhysics();
		void 		GetPhysicsResults();
		void 		ReleaseActor(NxActor* actor, NxScene* scene);
		void 		ReleaseScene(NxScene* scene);
		void 		ReleasePhysicsSDK(NxPhysicsSDK* pSDK);

		D3DXMATRIX	getPartMatrix(partEnum p);

	private:

		void	initRagdoll();

		NxActor* CreateGroundPlane();
		NxActor* CreateBox(const NxVec3& pos, const NxVec3& boxDim, const NxReal density);
		NxActor* CreateSphere(const NxVec3& pos, const NxReal radius, const NxReal density);
		NxActor* CreateCapsule(const NxVec3& pos, const NxReal height, const NxReal radius, const NxReal density);
		NxRevoluteJoint* CreateRevoluteJoint(NxActor* a0, NxActor* a1, const NxVec3& globalAnchor, const NxVec3& globalAxis);
		NxRevoluteJoint* CreateRevoluteJoint2(NxActor* a0, NxActor* a1, const NxVec3& localAnchor0,const NxVec3& localAnchor1, const NxVec3& localAxis0, const NxVec3& localAxis1);
		NxSphericalJoint* CreateSphericalJoint(NxActor* a0, NxActor* a1, const NxVec3& globalAnchor, const NxVec3& globalAxis);
		NxSphericalJoint* CreateBodySphericalJoint(NxActor* a0, NxActor* a1, const NxVec3& globalAnchor, const NxVec3& globalAxis);
		NxFixedJoint* CreateFixedJoint(NxActor* a0, NxActor* a1, const NxVec3& globalAnchor);

		float UpdateTime();
};

